namespace Brjnk.Common
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;

    /// <summary>
    /// </summary>
    public class BackgroundOperationList
    {
        #region Singleton

        private static BackgroundOperationList instance;

        static BackgroundOperationList()
        {
            instance = new BackgroundOperationList();
        }

        public static BackgroundOperationList Instance { get { return instance; } }

        #endregion Singleton

        private BackgroundOperationList()
        {
            operations = new List<BackgroundOperationStateBase>();
            visibleOperations = new ObservableCollection<BackgroundOperationStateBase>();
            visibleOperationsRO = new ReadOnlyObservableCollection<BackgroundOperationStateBase>(visibleOperations);
        }

        private List<BackgroundOperationStateBase> operations;

        private ObservableCollection<BackgroundOperationStateBase> visibleOperations;

        private System.Collections.ObjectModel.ReadOnlyObservableCollection<BackgroundOperationStateBase> visibleOperationsRO;

        public ReadOnlyObservableCollection<BackgroundOperationStateBase> VisibleOperations
        {
            get { return visibleOperationsRO; }
        }

        public void Add(BackgroundOperationStateBase operationState)
        {
            if (operations.Contains(operationState))
                throw new InvalidOperationException("Duplicite state.");

            operationState.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(operationState_PropertyChanged);
            operations.Add(operationState);
            bool visible = IsVisible(operationState);
            ApplyVisibility(operationState, visible);
        }

        private void ApplyVisibility(BackgroundOperationStateBase operationState, bool visible)
        {
            if (visible)
                if (!visibleOperations.Contains(operationState)) visibleOperations.Add(operationState);
            if (!visible)
                visibleOperations.Remove(operationState);
        }

        private bool IsVisible(BackgroundOperationStateBase operationState)
        {
            return operationState.IsRunning && operationState.ShowInList;
        }

        private void operationState_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            BackgroundOperationStateBase state = (BackgroundOperationStateBase)sender;
            if (e.PropertyName == "IsRunning" || e.PropertyName == "ShowInList")
            {
                bool visible = IsVisible(state);
                ApplyVisibility(state, visible);
            }
        }

        public void Remove(BackgroundOperationStateBase operationState)
        {
            if (!operations.Contains(operationState)) throw new InvalidOperationException("State not found.");
            operations.Remove(operationState);
            visibleOperations.Remove(operationState);
        }
    }
}